const { prisma } = require('../config/prisma');

class ServiceDepositPrisma {
  constructor(data) {
    this.id = data.id;
    this.user_id = data.user_id;
    this.service_id = data.service_id;
    this.amount = data.amount;
    this.deposit_type = data.deposit_type;
    this.operation_type = data.operation_type;
    this.status = data.status;
    this.transaction_id = data.transaction_id;
    this.refund_reason = data.refund_reason;
    this.created_at = data.created_at;
    this.updated_at = data.updated_at;
    
    // 关联数据
    this.user = data.users;
    this.service = data.local_services;
  }

  /**
   * 根据用户ID查找保证金记录
   * @param {BigInt} userId 用户ID
   * @param {Object} options 查询选项
   * @returns {Promise<{deposits: ServiceDepositPrisma[], total: number}>}
   */
  static async findByUserId(userId, options = {}) {
    const {
      page = 1,
      limit = 10,
      operation_type = null,
      status = null
    } = options;

    const where = {
      user_id: BigInt(userId)
    };

    if (operation_type) {
      where.operation_type = operation_type;
    }
    if (status) {
      where.status = status;
    }

    const [deposits, total] = await Promise.all([
      prisma.service_deposits.findMany({
        where,
        include: {
          users: {
            select: {
              id: true,
              nickname: true,
              avatar_url: true
            }
          },
          local_services: {
            select: {
              id: true,
              title: true
            }
          }
        },
        orderBy: { created_at: 'desc' },
        skip: (page - 1) * limit,
        take: limit
      }),
      prisma.service_deposits.count({ where })
    ]);

    return {
      deposits: deposits.map(deposit => new ServiceDepositPrisma(deposit)),
      total
    };
  }

  /**
   * 根据ID查找保证金记录
   * @param {BigInt} id 记录ID
   * @returns {Promise<ServiceDepositPrisma|null>}
   */
  static async findById(id) {
    if (id === null || id === undefined) {
      return null;
    }

    const deposit = await prisma.service_deposits.findUnique({
      where: { id: BigInt(id) },
      include: {
        users: true,
        local_services: true
      }
    });

    return deposit ? new ServiceDepositPrisma(deposit) : null;
  }

  /**
   * 创建保证金记录
   * @param {Object} data 记录数据
   * @returns {Promise<ServiceDepositPrisma>}
   */
  static async create(data) {
    const deposit = await prisma.service_deposits.create({
      data: {
        user_id: BigInt(data.user_id),
        service_id: data.service_id ? BigInt(data.service_id) : null,
        amount: data.amount,
        deposit_type: data.deposit_type || 'SERVICE',
        operation_type: data.operation_type || 'DEPOSIT',
        status: data.status || 'PENDING',
        transaction_id: data.transaction_id
      },
      include: {
        users: true,
        local_services: true
      }
    });

    return new ServiceDepositPrisma(deposit);
  }

  /**
   * 更新记录状态
   * @param {string} status 状态
   * @param {string} transactionId 交易ID
   * @returns {Promise<ServiceDepositPrisma>}
   */
  async updateStatus(status, transactionId = null) {
    const updateData = {
      status,
      updated_at: new Date()
    };

    if (transactionId) {
      updateData.transaction_id = transactionId;
    }

    const updatedDeposit = await prisma.service_deposits.update({
      where: { id: BigInt(this.id) },
      data: updateData,
      include: {
        users: true,
        local_services: true
      }
    });

    Object.assign(this, updatedDeposit);
    return this;
  }

  /**
   * 处理充值完成
   * @param {string} transactionId 交易ID
   * @returns {Promise<ServiceDepositPrisma>}
   */
  async completeDeposit(transactionId) {
    // 在事务中更新保证金记录和服务记录
    const result = await prisma.$transaction(async (tx) => {
      // 更新保证金记录状态
      const updatedDeposit = await tx.service_deposits.update({
        where: { id: BigInt(this.id) },
        data: {
          status: 'COMPLETED',
          transaction_id: transactionId,
          updated_at: new Date()
        },
        include: {
          users: true,
          local_services: true
        }
      });

      // 如果是针对特定服务的保证金，更新服务的已付保证金
      if (this.service_id) {
        await tx.local_services.update({
          where: { id: BigInt(this.service_id) },
          data: {
            deposit_paid: {
              increment: Number(this.amount)
            }
          }
        });
      }

      return updatedDeposit;
    });

    Object.assign(this, result);
    return this;
  }

  /**
   * 处理退款完成
   * @param {string} refundReason 退款原因
   * @returns {Promise<ServiceDepositPrisma>}
   */
  async completeRefund(refundReason) {
    // 在事务中更新保证金记录和服务记录
    const result = await prisma.$transaction(async (tx) => {
      // 更新保证金记录状态
      const updatedDeposit = await tx.service_deposits.update({
        where: { id: BigInt(this.id) },
        data: {
          status: 'COMPLETED',
          refund_reason: refundReason,
          updated_at: new Date()
        },
        include: {
          users: true,
          local_services: true
        }
      });

      // 如果是针对特定服务的保证金，更新服务的已付保证金
      if (this.service_id && this.operation_type === 'REFUND') {
        await tx.local_services.update({
          where: { id: BigInt(this.service_id) },
          data: {
            deposit_paid: {
              decrement: Number(this.amount)
            }
          }
        });
      }

      return updatedDeposit;
    });

    Object.assign(this, result);
    return this;
  }

  /**
   * 获取用户的总保证金余额
   * @param {BigInt} userId 用户ID
   * @returns {Promise<number>}
   */
  static async getUserDepositBalance(userId) {
    const result = await prisma.service_deposits.aggregate({
      where: {
        user_id: BigInt(userId),
        status: 'COMPLETED'
      },
      _sum: {
        amount: true
      }
    });

    // 计算充值减去退款的余额
    const deposits = await prisma.service_deposits.findMany({
      where: {
        user_id: BigInt(userId),
        status: 'COMPLETED'
      },
      select: {
        amount: true,
        operation_type: true
      }
    });

    let balance = 0;
    deposits.forEach(deposit => {
      if (deposit.operation_type === 'DEPOSIT') {
        balance += Number(deposit.amount);
      } else if (deposit.operation_type === 'REFUND') {
        balance -= Number(deposit.amount);
      }
    });

    return Math.max(0, balance);
  }

  /**
   * 序列化为普通对象
   * @returns {Object}
   */
  toJSON() {
    return {
      id: this.id?.toString(),
      user_id: this.user_id?.toString(),
      service_id: this.service_id?.toString(),
      amount: Number(this.amount),
      deposit_type: this.deposit_type,
      operation_type: this.operation_type,
      status: this.status,
      transaction_id: this.transaction_id,
      refund_reason: this.refund_reason,
      created_at: this.created_at,
      updated_at: this.updated_at,
      user: this.user,
      service: this.service
    };
  }
}

module.exports = ServiceDepositPrisma;